Skip to content

feat: add 51 Tier 1+2 operations across DynamoDB, Lambda, IAM, EventBridge#16

Merged
tyrchen merged 16 commits intomasterfrom
feat/service-operations-gap
Mar 26, 2026
Merged

feat: add 51 Tier 1+2 operations across DynamoDB, Lambda, IAM, EventBridge#16
tyrchen merged 16 commits intomasterfrom
feat/service-operations-gap

Conversation

@tyrchen
Copy link
Copy Markdown
Owner

@tyrchen tyrchen commented Mar 26, 2026

Summary

Implements the service operations gap spec across 6 phases, adding 51 new operations to close the most impactful gaps between RustStack and LocalStack.

Phase 1 — DynamoDB Transactions, TTL, Tagging (7 ops)

  • TransactGetItems, TransactWriteItems with condition expression evaluation, deterministic lock ordering, and CancellationReasons in error responses
  • UpdateTimeToLive, DescribeTimeToLive (metadata storage, no background deletion)
  • TagResource, UntagResource, ListTagsOfResource with 50-tag limit and aws: prefix validation

Phase 2 — Lambda Layers (9 ops)

  • PublishLayerVersion, GetLayerVersion, GetLayerVersionByArn, ListLayerVersions, ListLayers, DeleteLayerVersion
  • AddLayerVersionPermission, GetLayerVersionPolicy, RemoveLayerVersionPermission
  • New LayerStore with DashMap + BTreeMap version tracking

Phase 3 — Lambda Event Source Mappings (5 ops)

  • CreateEventSourceMapping, GetEventSourceMapping, UpdateEventSourceMapping, DeleteEventSourceMapping, ListEventSourceMappings
  • New EventSourceMappingStore with UUID-based identification, function/source filters

Phase 4 — IAM OIDC Providers + Resource Tagging (10 ops)

  • CreateOpenIDConnectProvider, GetOpenIDConnectProvider, DeleteOpenIDConnectProvider, ListOpenIDConnectProviders
  • TagPolicy, UntagPolicy, ListPolicyTags, TagInstanceProfile, UntagInstanceProfile, ListInstanceProfileTags

Phase 5 — EventBridge Remaining Operations (26 ops → 25 real + 1 deauthorize)

  • Archives (5), Replays (4), API Destinations (5), Connections (6), Endpoints (5)
  • Generic CRUD pattern with DashMap<String, serde_json::Value> storage per resource type

Phase 6 — Tier 2 Grab Bag (10 ops)

  • DynamoDB: DescribeLimits (hardcoded), DescribeEndpoints (regional endpoint)
  • Lambda: PutFunctionConcurrency, GetFunctionConcurrency, DeleteFunctionConcurrency
  • Lambda: PutFunctionEventInvokeConfig, GetFunctionEventInvokeConfig, UpdateFunctionEventInvokeConfig, DeleteFunctionEventInvokeConfig, ListFunctionEventInvokeConfigs

Bug Fixes

  • Reverted cargo +nightly fmt corruption of \n escape sequences in ruststack-auth string literals (6 test failures)
  • Fixed TOCTOU in handle_tag_resource: tags mutated before count validation now uses clone-validate-commit pattern

Test plan

  • All 700+ existing unit tests pass (cargo test — zero failures)
  • 40+ new unit tests for layers, ESM, resolvers
  • cargo clippy -- -D warnings clean on all modified crates
  • Auth module: 42/42 tests pass (was 36/42 before fix)
  • Integration tests with aws-sdk-rust for new operations
  • Terraform plan/apply cycle validation

🤖 Generated with Claude Code

tyrchen and others added 16 commits March 26, 2026 11:12
Add 7 new DynamoDB operations: TransactGetItems, TransactWriteItems,
UpdateTimeToLive, DescribeTimeToLive, TagResource, UntagResource,
ListTagsOfResource.

Transactions implement deterministic lock ordering on (table, partition_key)
pairs to prevent deadlocks, with full condition expression evaluation and
CancellationReasons in error responses. TTL stores metadata without
background deletion. Tagging validates max 50 tags, key/value length
limits, and reserved aws: prefix.

Also includes cargo fmt reformatting across the workspace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 9 Lambda Layer operations: PublishLayerVersion, GetLayerVersion,
GetLayerVersionByArn, ListLayerVersions, ListLayers, DeleteLayerVersion,
AddLayerVersionPermission, GetLayerVersionPolicy, RemoveLayerVersionPermission.

Introduces LayerStore with DashMap-backed concurrent storage, LayerRecord
and LayerVersionRecord types, layer ARN generation/parsing helpers, and
resource-based policy support per layer version. Includes 20 new unit tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 5 Lambda Event Source Mapping operations: CreateEventSourceMapping,
GetEventSourceMapping, UpdateEventSourceMapping, DeleteEventSourceMapping,
ListEventSourceMappings.

Introduces EventSourceMappingStore with DashMap-backed concurrent storage,
EventSourceMappingRecord for mapping state, UUID-based identification,
filtering by function name and event source ARN, and marker-based
pagination. Includes 22 new unit tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 10 IAM operations: CreateOpenIDConnectProvider, GetOpenIDConnectProvider,
DeleteOpenIDConnectProvider, ListOpenIDConnectProviders, TagPolicy,
UntagPolicy, ListPolicyTags, TagInstanceProfile, UntagInstanceProfile,
ListInstanceProfileTags.

Introduces OidcProviderRecord type and oidc_providers DashMap in IamStore.
OIDC provider ARNs use normalized URL (host+path). Policy and instance
profile tagging reuse existing tag merge/validate patterns with 50-tag limit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… endpoint operations (Phase 5)

Replace 26 EventBridge Phase 3 operation stubs with real CRUD
implementations: Archives (5), Replays (4), API Destinations (5),
Connections (6), Endpoints (5).

Uses DashMap<String, serde_json::Value> storage per resource type with
generic CRUD helpers for create/describe/update/delete/list patterns.
Each resource gets proper ARN generation, state management, and timestamps.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DynamoDB: Add DescribeLimits (hardcoded 80000/40000 capacity units) and
DescribeEndpoints (returns regional endpoint with 1440-min cache).

Lambda: Add 8 operations for concurrency and event invoke configuration:
PutFunctionConcurrency, GetFunctionConcurrency, DeleteFunctionConcurrency,
PutFunctionEventInvokeConfig, GetFunctionEventInvokeConfig,
UpdateFunctionEventInvokeConfig, DeleteFunctionEventInvokeConfig,
ListFunctionEventInvokeConfigs.

Concurrency stored as optional i32 on FunctionRecord. Event invoke configs
stored per qualifier with max retry attempts (0-2), max event age
(60-21600s), and destination config (on_success/on_failure ARNs).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Revert cargo nightly fmt changes to ruststack-auth that corrupted \n
escape sequences in string literals, breaking SigV4 signature computation
and 6 tests.

Fix TOCTOU in handle_tag_resource: tags were mutated before count
validation, persisting over-limit tags on error. Now clones, merges,
validates, then commits atomically.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Run cargo +nightly fmt across auth module, then add #[rustfmt::skip]
annotations to 7 string expressions where nightly rustfmt's
format_strings option corrupts \n escape sequences. This satisfies
the CI format check while preserving correct SigV4 string semantics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Collapse let = \n "string" into let = "string" for presigned.rs and
multipart.rs to match CI nightly rustfmt expectations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Drop impl cannot be async, so spawn the file removal on the tokio
runtime via Handle::try_current(). Falls back gracefully when no runtime
is active (e.g. test teardown). Fixes clippy disallowed_methods lint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 19 integration tests covering all new operations:
- DynamoDB (6): tagging, TTL, transactions (write+get, condition failure),
  describe_limits, describe_endpoints
- Lambda (8): layer publish/get/list/delete, ESM create/update/delete/list,
  function concurrency, event invoke config
- IAM (5): OIDC provider CRUD, policy tags, instance profile tags
- EventBridge (5): archive CRUD, connection, API destination

Also fix pre-existing clippy lint: replace std::fs::remove_file with
tokio::fs::remove_file in S3 StoredData Drop impl.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Normalize Lambda API date prefixes for layers (2018-10-31),
  event-source-mappings (2015-03-31), and consolidate concurrency and
  event-invoke-config routes to use 2015-03-31 matching SDK behavior
- Fix EventBridge timestamps: use epoch seconds (float) instead of
  RFC3339 strings for CreationTime/LastModifiedTime
- Fix DynamoDB DescribeLimits test: correct table vs account capacity
  expected values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add /layers and /event-source-mappings path matching to the gateway's
is_lambda_path() so these requests route to Lambda instead of falling
through to S3.

Fix test_should_put_and_get_function_concurrency to use
get_function_concurrency directly instead of checking get_function
response which doesn't include Concurrency field.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Lambda ESM operations use PascalCase wire format (EventSourceArn, not
eventSourceArn). Fix CreateEventSourceMappingInput,
UpdateEventSourceMappingInput, EventSourceMappingConfiguration, and
ListEventSourceMappingsOutput from camelCase to PascalCase.

Add #[rustfmt::skip] to presigned.rs and multipart.rs test strings
that different nightly versions format inconsistently.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
EventBridge now_timestamp returns i64 epoch seconds (avoids clippy
cast_precision_loss). Lambda ESM last_modified changed from ISO string
to f64 epoch seconds matching the AWS SDK wire format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tements

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tyrchen tyrchen merged commit 2ee83da into master Mar 26, 2026
32 checks passed
@tyrchen tyrchen deleted the feat/service-operations-gap branch March 26, 2026 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant